<template>
	<div class="wrap">
		<input type="text" v-model="value" placeholder="发布的ID，不用带live/" />
		<div class="" @click="startPublish()">点击发布</div>
		<div class="" @click="stopPublish()">点击停止发布</div>
		<div class="" @click="startPlay()">点击播放</div>
		<div class="" @click="stopPlay()">点击停止播放</div>
		<br />
		<div class="" @click="getShareScreen()">
			点击获取全部窗口(点击选择一个窗口后点击发布，发布成功再点击播放)
		</div>
		<div
			:class="currentShareScreenId == window.id ? 'window-bg' : ''"
			v-for="window in shareScreenIdArr"
			:key="window.id"
			@click="selectShareScreen(window)"
		>
			{{
				window.id.indexOf("screen") !== -1
					? "屏幕------" + window.name + "ID------" + window.id
					: "窗口------" + window.name + "ID------" + window.id
			}}
		</div>
        <div class="" @click="openWebrtc()">点击打开webrtc</div>
		<div v-if="shareScreenIdArr.length > 0" class="" @click="clearWindow()">
			不选择任何窗口
		</div>

		<div class="video-wrap">
			<div class="">发布的流</div>
			<video
				id="publishVideo"
				muted
				autoplay
				controls
				playsinline
				class="video-item"
			></video>
		</div>
		<div class="video-wrap">
			<div class="">播放的流</div>
			<video
				id="playVideo"
				:muted="false"
				autoplay
				controls
				playsinline
				class="video-item"
			></video>
		</div>

        <Draw></Draw>
	</div>
</template>

<script>
import Draw from "@/components/Draw.vue";
export default {
	name: "Home",
    components: {
        Draw
    },
	data() {
		return {
			value: "tch_1",
			publishPC: null,
			playPC: null,
			publishUrl: "",
			baseUrl: "http://192.168.2.111:8080",
			shareScreenIdArr: [],
			currentShareScreenId: null,
		};
	},

	mounted() {},
	methods: {
		// 获取本地视频流
		getLocalStream() {
			return new Promise(async (resolve, reject) => {
				const mediaStream = await navigator.mediaDevices.getUserMedia({
					video: true,
					audio: true,
				});
				console.log("mediaStream", mediaStream);
				let dom = document.getElementById("publishVideo");
				if (dom) {
					dom.srcObject = mediaStream;
				}
				resolve(mediaStream);
			});
		},
		// 开始发布
		async startPublish() {
			let streamId = this.value;
			console.log("开始发布", streamId);
			let mediaStream = null;
			if (this.currentShareScreenId) {
				mediaStream = document.getElementById("publishVideo").srcObject;
			} else {
				mediaStream = await this.getLocalStream();
			}

			this.publishPC = new RTCPeerConnection();

			this.publishPC.oniceconnectionstatechange = () => {
				console.log(
					"oniceconnectionstatechange",
					this.publishPC.iceConnectionState
				);
				if (this.publishPC.iceConnectionState == "disconnected") {
					console.log("发布结束");
					document.getElementById("playVideo").srcObject = null;
					this.stopTrack();
					this.$message.error("发布结束");
				}
			};
			this.publishPC.onicecandidate = (e) => {
				console.log("onicecandidate", e.candidate);
			};
            // this.publishPC.addTransceiver("video", {
            // direction: 'sendrecv',
            // sendEncodings: [
            //     { rid: 'r0', maxBitrate: 10000000 ,maxFramerate:60},
            //     { rid: 'r1', maxBitrate: 5000000, scaleResolutionDownBy: 2.0,maxFramerate:60 }
            // ]
            // });
			mediaStream.getTracks().forEach((t) => {
                const sender = this.publishPC.addTrack(t, mediaStream);
                // // 获取编码参数
                const params = sender.getParameters();
                if (params.encodings.length>0){
                    params.encodings[0].networkPriority='high';
                    params.encodings[0].priority='high';
                    params.encodings[0].maxBitrate = 40000000;
                    params.encodings[0].maxFramerate=60;
                    params.encodings[0].active=true;
                    sender.setParameters(params);
                }
				// this.publishPC.addTrack(t, mediaStream);
			});
			const offer = await this.publishPC.createOffer();
			await this.publishPC.setLocalDescription(offer);

			let publishUrl =
				this.baseUrl + `/webrtc/push/live/${streamId}?name=${streamId}`;
			console.log("publishUrl", publishUrl);
			this.publishUrl = publishUrl;

			const result = await fetch(this.publishUrl, {
				method: "POST",
				mode: "cors",
				cache: "no-cache",
				credentials: "include",
				redirect: "follow",
				referrerPolicy: "no-referrer",
				headers: { "Content-Type": "application/sdp" },
				body: offer.sdp,
			});
			const remoteSdp = await result.text();
			console.warn("发布结果", result);

			if (result.status == 200 || result.status == 201) {
				this.$message.success("发布成功");
			} else {
				this.$message.error("发布失败");
				this.stopTrack();
				return;
			}

			// document.getElementById("publish-remoteSdp").innerText = remoteSdp;
			await this.publishPC.setRemoteDescription(
				new RTCSessionDescription({ type: "answer", sdp: remoteSdp })
			);
		},
		// 结束发布
		async stopPublish() {
			let streamId = this.value;
			const result = await fetch(
				this.baseUrl + `/api/closestream?streamPath=live/${streamId}`,
				{
					method: "GET",
					mode: "cors",
					cache: "no-cache",
					credentials: "include",
					redirect: "follow",
					referrerPolicy: "no-referrer",
				}
			);
			console.log("关闭流结果", result);
			document.getElementById("playVideo").srcObject = null;
			if (result.status == 200 || result.status == 201) {
				this.publishPC?.close();
				this.stopTrack();
			}
		},
		// 播放流
		async startPlay() {
			let streamId = this.value;
			let dom = document.getElementById("playVideo");
			this.playPC = new RTCPeerConnection();
			this.playPC.ontrack = (e) => {
				console.log("ontrack", e);
				if (e.streams.length === 0 || !document.getElementById("playVideo"))
					return;
				dom.srcObject = e.streams[0];
			};
			this.playPC.oniceconnectionstatechange = (e) => {
				console.log(
					"oniceconnectionstatechange",
					e,
					this.playPC,
					this.playPC.iceConnectionState
				);
				if (this.playPC.iceConnectionState == "connected") {
					console.log("播放成功", streamId);
					this.$message.success("播放成功");
				}
				if (this.playPC.iceConnectionState == "disconnected") {
					console.log("播放结束", streamId);
					this.$message.error("播放结束");
					document.getElementById("playVideo").srcObject = null;
				}
			};
			this.playPC.onconnectionstatechange = (e) => {
				console.log("state changed", e, this.playPC.connectionState);
			};
			this.playPC.onicecandidate = (e) => {
				console.log("onicecandidate", e);
			};
			this.playPC.addTransceiver("video", { direction: "recvonly" });
			this.playPC.addTransceiver("audio", { direction: "recvonly" });
			// const dc = this.playPC.createDataChannel('sdp');
			const offer = await this.playPC.createOffer();
			await this.playPC.setLocalDescription(offer);
			const searchParams = new URLSearchParams(location.search);
			const streamPath = searchParams.get("streamPath") || "live/" + streamId;
			searchParams.delete("streamPath");
			const result = await fetch(this.baseUrl + `/webrtc/play/${streamPath}`, {
				method: "POST",
				mode: "cors",
				cache: "no-cache",
				credentials: "include",
				redirect: "follow",
				referrerPolicy: "no-referrer",
				headers: { "Content-Type": "application/sdp" },
				body: offer.sdp,
			});
			console.log("播放结果", result);
			if (result.status == 200 || result.status == 201) {
				console.log("播放成功");
			} else {
				console.error("播放失败", result);
				this.$message.error("播放失败");
				this.stopPlay();
				return;
			}
			const remoteSdp = await result.text();
			// document.getElementById("play-remoteSdp").innerText = remoteSdp;
			await this.playPC.setRemoteDescription(
				new RTCSessionDescription({ type: "answer", sdp: remoteSdp })
			);
		},
		// 结束播放流
		stopPlay() {
			document.getElementById("playVideo").srcObject = null;
			this.playPC?.close();
		},
		// 停止轨道
		stopTrack() {
			let dom = document.getElementById("publishVideo");
			if (dom && dom.srcObject) {
				var tracks = dom.srcObject.getTracks(); // if only audio was requested, this will be an array with one MediaStreamTrack
				tracks.map((track) => {
					track.stop();
				});
				document.getElementById("publishVideo").srcObject = null;
			}
		},
		// 切换视频源
		switchSource(equipIdObj) {
			let dom = document.getElementById(this.data.streamId);
			if (dom) {
				dom.srcObject.getTracks().forEach((t) => {
					// t.stop();
					dom.srcObject.removeTrack(t);
				});

				navigator.mediaDevices
					.getUserMedia({
						video: {
							deviceId: equipIdObj.video,
						},
						audio: {
							deviceId: equipIdObj.microPhone,
						},
					})
					.then((stream) => {
						let senders = this.publishPC.getSenders();

						senders.map((track) => {
							if (track.track.kind === "video") {
								track.replaceTrack(stream.getVideoTracks()[0]);
							}
							if (track.track.kind === "audio") {
								track.replaceTrack(stream.getAudioTracks()[0]);
							}
						});
						document.getElementById(this.data.streamId).srcObject = stream;
						console.log("切换视频源publishPC", this.publishPC, senders, stream);
					});
			}
		},
		// 获取屏幕的窗口流id
		getShareScreen() {
			window.electronAPI.navigatorShare(["screen", "window"]).then((res) => {
				this.shareScreenIdArr = res;
				console.log("共享屏幕的所有屏幕流", this.shareScreenIdArr);
			});
		},
		// 选择窗口
		selectShareScreen(screen) {
			this.currentShareScreenId = screen.id;
			// 获取屏幕流
			this.changeScreenStream(screen.id).then((res) => {
				console.log("切换屏幕流成功");
				document.getElementById("publishVideo").srcObject = res;
			});
		},
		clearWindow() {
			this.currentShareScreenId = null;
			document.getElementById("publishVideo").srcObject = null;
		},
		// 获取屏幕流
		changeScreenStream(screenId) {
			return new Promise((resolve, reject) => {
				console.warn("id:", screenId);
				let videoMediaOption = {
					audio: {
						mandatory: {
							chromeMediaSource: "desktop",
						},
					},
					video: {
						mandatory: {
							chromeMediaSource: "desktop",
							chromeMediaSourceId: screenId,
							maxWidth: 1920,
							maxHeight: 1080,
                            minFrameRate:30,
                            maxFrameRate:60,
						},
					},
				};
				navigator.mediaDevices
					.getUserMedia(videoMediaOption)
					.then((mediaStream) => {
                        mediaStream.getTracks().forEach((track) => {
                            track.contentHint = 'detail';
                        });
						resolve(mediaStream);
					})
					.catch((err) => {
						reject(err);
					});
			});
		},
        openWebrtc(){
            window.electronAPI.openWebrtc()
        }
	},
	beforeDestroy() {
		this.stopTrack();
		this.publishPC?.close();
		this.playPC?.close();
	},
};
</script>

<style lang="scss" scoped>
.video-wrap {
	display: inline-block;
	border: 1px solid #ccc;
}
.video-item {
	width: 300px;
	height: 200px;
	object-fit: cover;
}
.window-bg {
	background: red;
}
</style>
